Skip to content

refactor(rust_crypto): lift RSA backend to rsa 0.10.0-rc.17#1

Draft
EffortlessSteven wants to merge 3 commits intomasterfrom
codex/rust-crypto-rsa-010
Draft

refactor(rust_crypto): lift RSA backend to rsa 0.10.0-rc.17#1
EffortlessSteven wants to merge 3 commits intomasterfrom
codex/rust-crypto-rsa-010

Conversation

@EffortlessSteven
Copy link
Copy Markdown
Owner

@EffortlessSteven EffortlessSteven commented Apr 15, 2026

Scope

  • rust_crypto backend only
  • no public API changes
  • no aws_lc_rs changes
  • no crate-wide signature 3 migration
  • no crate-wide sha2 0.11 migration

Dependency note

  • This uses the currently published crates.io 0.10 line for RSA, which is rsa 0.10.0-rc.17.

Changes

  • replace wrapper-based RSA signing with low-level key operations
  • prehash explicitly and sign/verify digest bytes with Pkcs1v15Sign / Pss
  • move RSA bigint handling to BoxedUint
  • decouple ECDSA from rsa::pkcs8
  • preserve RSA modulus/exponent component behavior
  • add a wasm-target-only getrandom 0.4 alias so the existing wasm-pack CI commands keep working

Existing coverage touched by this change

  • PEM PKCS#1 and PKCS#8 RSA round-trips
  • DER round-trips
  • modulus/exponent decode via DecodingKey::from_rsa_components
  • JWK decode
  • JWK generation from an encoding key

Validated locally

  • cargo fmt --check
  • cargo clippy --all-targets --features rust_crypto -- -D warnings
  • cargo clippy --all-targets --features aws_lc_rs -- -D warnings
  • cargo test --features rust_crypto
  • cargo test --no-default-features --features rust_crypto
  • cargo test --features aws_lc_rs
  • cargo test --no-default-features --features aws_lc_rs
  • wasm-pack test --node --features rust_crypto,getrandom/js
  • wasm-pack test --node --no-default-features --features rust_crypto,getrandom/js

Non-goal

  • does not claim to fully resolve Marvin / RUSTSEC-2023-0071

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 15, 2026

📝 Walkthrough

Summary by CodeRabbit

  • Chores

    • Upgraded cryptography and randomness dependencies for newer releases and better WASM/platform support.
    • Adjusted optional dependency mappings for improved compatibility.
  • Refactor

    • Updated RSA and ECDSA internals for compatibility with upgraded libraries.
    • Normalized RSA public key components and switched to pre-hashing for RSA signing/verification to ensure consistent behavior.

Walkthrough

Replaced rand with rand10; upgraded rsa to 0.10.0-rc.17 with sha2; added getrandom v0.4 for wasm; adjusted ECDSA PKCS#8 import; added leading-zero trimming for RSA JWK fields; reworked RSA to pre-hash messages, use RsaPrivateKey with scheme constructors, and switch RNG to rand10.

Changes

Cohort / File(s) Summary
Dependency Updates
Cargo.toml
Replaced rand with rand10 = { package = "rand", version = "0.10", optional = true, features = ["std","thread_rng"], default-features = false }; upgraded rsa0.10.0-rc.17 and enabled sha2; added getrandom_04 = { package = "getrandom", version = "0.4", features = ["wasm_js"] } for wasm; updated rust_crypto feature to include rand10.
ECDSA Module
src/crypto/rust_crypto/ecdsa.rs
Replaced imported PKCS#8 private-key decode trait from rsa::pkcs8::DecodePrivateKey to p256::pkcs8::DecodePrivateKey.
RSA Logic & Helpers
src/crypto/rust_crypto/mod.rs, src/crypto/rust_crypto/rsa.rs
Added trim_leading_zeroes and apply to JWK n/e; changed RSA signing/verifying to pre-hash via H::digest(msg) and pass digest bytes to sign/verify APIs; construct RsaPrivateKey with scheme-specific constructors (Pss::<H>, Pkcs1v15Sign::<H>); switched RNG usage from rand::thread_rng() to rand10::rng(); convert byte slices to BoxedUint via helper; removed unused imports/types.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Hasher
    participant RSA_Module
    participant RNG

    Client->>Hasher: request H::digest(msg)
    Hasher-->>Client: digest bytes
    Client->>RSA_Module: sign(digest bytes, scheme)
    alt scheme == PSS
        RSA_Module->>RNG: request randomness
        RNG-->>RSA_Module: random nonce
    end
    RSA_Module-->>Client: signature
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

A rabbit hops through code at night,
Swapping rand for rand10 — light! 🐇
Trims the zeros, hashes then signs,
RNG scatters careful lines,
Crypto carrots gleam so bright. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: refactoring the rust_crypto backend to upgrade RSA from 0.9.6 to 0.10.0-rc.17.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, providing scope, specific changes, validation details, and non-goals.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/rust-crypto-rsa-010

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the rsa dependency to version 0.10.0-rc.17 and refactors the RSA signing and verification logic to use the new API, specifically replacing BigUint with BoxedUint. It also introduces a trim_leading_zeroes helper and updates rand and getrandom dependencies. Feedback indicates that the specified versions for rand (0.10) and getrandom (0.4) are non-existent on crates.io, and the bits_precision calculation for BoxedUint requires rounding to the nearest multiple of 64 to prevent potential runtime errors.

Comment thread Cargo.toml
p384 = { version = "0.13.0", optional = true, features = ["ecdsa"] }
rand = { version = "0.8.5", optional = true, features = ["std"], default-features = false }
rsa = { version = "0.9.6", optional = true }
rand10 = { package = "rand", version = "0.10", optional = true, features = ["std", "thread_rng"], default-features = false }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The dependency rand version 0.10 does not currently exist on crates.io (the latest stable is 0.9.0). Using a non-existent version will cause compilation to fail. If you intended to use the latest version that supports the new rand_core ecosystem used by rsa 0.10, you likely meant version 0.9.

Suggested change
rand10 = { package = "rand", version = "0.10", optional = true, features = ["std", "thread_rng"], default-features = false }
rand10 = { package = "rand", version = "0.9", optional = true, features = ["std", "thread_rng"], default-features = false }

Comment thread Cargo.toml
[target.'cfg(target_arch = "wasm32")'.dependencies]
js-sys = "0.3"
getrandom = "0.2"
getrandom_04 = { package = "getrandom", version = "0.4", features = ["wasm_js"] }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The dependency getrandom version 0.4 does not currently exist on crates.io (the latest stable is 0.3.0). Additionally, the feature name for WebAssembly support in getrandom 0.3+ is wasm-js (with a hyphen), not wasm_js. Please verify the intended version and feature name.

Suggested change
getrandom_04 = { package = "getrandom", version = "0.4", features = ["wasm_js"] }
getrandom_03 = { package = "getrandom", version = "0.3", features = ["wasm-js"] }

Comment on lines +23 to +25
let bits_precision =
u32::try_from(bytes.len().saturating_mul(8)).map_err(signature::Error::from_source)?;
BoxedUint::from_be_slice(bytes, bits_precision).map_err(signature::Error::from_source)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The bits_precision calculation is likely to cause a panic or error for many RSA keys. crypto-bigint (used by rsa 0.10) requires bits_precision to be a multiple of Limb::BITS (which is 32 or 64 depending on the target). For common RSA exponents like 65537 ([1, 0, 1]), bytes.len() * 8 is 24, which is not a multiple of 64, causing BoxedUint::from_be_slice to return a Precision error. You should round the precision up to the nearest multiple of 64 to ensure compatibility across platforms.

Suggested change
let bits_precision =
u32::try_from(bytes.len().saturating_mul(8)).map_err(signature::Error::from_source)?;
BoxedUint::from_be_slice(bytes, bits_precision).map_err(signature::Error::from_source)
let bits = bytes.len().saturating_mul(8);
let bits_precision = u32::try_from(bits.next_multiple_of(64)).map_err(signature::Error::from_source)?;
BoxedUint::from_be_slice(bytes, bits_precision).map_err(signature::Error::from_source)

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/crypto/rust_crypto/rsa.rs (2)

77-94: ⚠️ Potential issue | 🟠 Major

Parse and validate the RSA private key in new().

The signer now stores raw EncodingKey bytes and reparses PKCS#1 on every try_sign(). That delays invalid-key detection until first use and adds avoidable DER parsing on the hot signing path. Store RsaPrivateKey in the signer instead.

Proposed direction
-        pub struct $name(EncodingKey);
+        pub struct $name(RsaPrivateKey);

         impl $name {
             pub(crate) fn new(encoding_key: &EncodingKey) -> Result<Self> {
                 if encoding_key.family() != AlgorithmFamily::Rsa {
                     return Err(new_error(ErrorKind::InvalidKeyFormat));
                 }

-                Ok(Self(encoding_key.clone()))
+                Ok(Self(
+                    RsaPrivateKey::from_pkcs1_der(encoding_key.inner())
+                        .map_err(|e| new_error(ErrorKind::InvalidRsaKey(e.to_string())))?,
+                ))
             }
         }

Then update try_sign_rsa() to accept &RsaPrivateKey instead of &EncodingKey.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/crypto/rust_crypto/rsa.rs` around lines 77 - 94, The signer currently
stores an EncodingKey and defers PKCS#1 parsing to try_sign; change the
macro-generated struct in define_rsa_signer to parse and validate the RSA
private key in new() and store a parsed RsaPrivateKey (not EncodingKey) as the
inner field; update new() to convert/parse the EncodingKey bytes into an
RsaPrivateKey (returning Err on parse failure) while keeping the AlgorithmFamily
check, adjust the impl Signer for $name so try_sign() calls try_sign_rsa with
&RsaPrivateKey, and update try_sign_rsa signature to accept &RsaPrivateKey
instead of &EncodingKey (and propagate any required type changes).

105-129: ⚠️ Potential issue | 🟠 Major

Materialize RsaPublicKey eagerly in new().

This verifier has the same regression: new() accepts any RSA-family key without parsing it, and every verify() call rebuilds the public key from DER or (n, e). Parse once in the constructor so invalid keys fail early and verification stays off the parsing path.

Proposed direction
-        pub struct $name(DecodingKey);
+        pub struct $name(RsaPublicKey);

Build the RsaPublicKey inside new() from either DecodingKeyKind::SecretOrDer or DecodingKeyKind::RsaModulusExponent, then pass &self.0 into a verify_rsa() helper that accepts &RsaPublicKey.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/crypto/rust_crypto/rsa.rs` around lines 105 - 129, The verifier currently
stores only DecodingKey in the generated struct from define_rsa_verifier and
defers parsing to each verify() call; change the impl new(decoding_key:
&DecodingKey) for the generated $name to eagerly parse and store an RsaPublicKey
(construct it from DecodingKeyKind::SecretOrDer or
DecodingKeyKind::RsaModulusExponent) so invalid keys fail at construction, and
update verify() to call verify_rsa helper overloads that accept &RsaPublicKey
(instead of rebuilding the key from DER/(n,e) on every call); ensure the
constructor returns Err for invalid keys and the struct holds the parsed
RsaPublicKey used by verify().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/crypto/rust_crypto/rsa.rs`:
- Around line 77-94: The signer currently stores an EncodingKey and defers
PKCS#1 parsing to try_sign; change the macro-generated struct in
define_rsa_signer to parse and validate the RSA private key in new() and store a
parsed RsaPrivateKey (not EncodingKey) as the inner field; update new() to
convert/parse the EncodingKey bytes into an RsaPrivateKey (returning Err on
parse failure) while keeping the AlgorithmFamily check, adjust the impl Signer
for $name so try_sign() calls try_sign_rsa with &RsaPrivateKey, and update
try_sign_rsa signature to accept &RsaPrivateKey instead of &EncodingKey (and
propagate any required type changes).
- Around line 105-129: The verifier currently stores only DecodingKey in the
generated struct from define_rsa_verifier and defers parsing to each verify()
call; change the impl new(decoding_key: &DecodingKey) for the generated $name to
eagerly parse and store an RsaPublicKey (construct it from
DecodingKeyKind::SecretOrDer or DecodingKeyKind::RsaModulusExponent) so invalid
keys fail at construction, and update verify() to call verify_rsa helper
overloads that accept &RsaPublicKey (instead of rebuilding the key from
DER/(n,e) on every call); ensure the constructor returns Err for invalid keys
and the struct holds the parsed RsaPublicKey used by verify().

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ac006ea2-72a5-443a-a586-173930795249

📥 Commits

Reviewing files that changed from the base of the PR and between 0c5931a and ebb5421.

📒 Files selected for processing (4)
  • Cargo.toml
  • src/crypto/rust_crypto/ecdsa.rs
  • src/crypto/rust_crypto/mod.rs
  • src/crypto/rust_crypto/rsa.rs

@EffortlessSteven EffortlessSteven changed the title refactor(rust_crypto): lift RSA backend to rsa 0.10 refactor(rust_crypto): lift RSA backend to rsa 0.10.0-rc.17 Apr 15, 2026
@EffortlessSteven
Copy link
Copy Markdown
Owner Author

Addressing the bot suggestions in one place:

  • rand 0.10.1 and getrandom 0.4.2 are both available in the registry used for local validation here, and the wasm compatibility shim was validated with the existing wasm-pack commands.
  • I’m keeping bits_precision = len * 8; that matches crypto-bigint’s own BoxedUint DER decode path.
  • I’m not taking the eager parse/store suggestions in this branch because the scope here is the minimal rust_crypto RSA backend lift. Existing coverage across PEM, DER, (n, e), JWK decode, and JWK generation is green on the updated branch.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/crypto/rust_crypto/rsa.rs`:
- Around line 24-28: In to_boxed_uint remove the unused bits_precision
computation and call BoxedUint::from_be_slice with only the bytes slice (i.e.,
replace BoxedUint::from_be_slice(bytes, bits_precision) with
BoxedUint::from_be_slice(bytes)) and map its error with
signature::Error::from_source so the function compiles against the rsa
0.10.0-rc.17 API; keep the function signature and the final
map_err(signature::Error::from_source) behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c65e217a-fba8-447e-a5b6-951bf39dcc5e

📥 Commits

Reviewing files that changed from the base of the PR and between ebb5421 and 587c7bc.

📒 Files selected for processing (2)
  • Cargo.toml
  • src/crypto/rust_crypto/rsa.rs

Comment on lines +24 to +28
fn to_boxed_uint(bytes: &[u8]) -> std::result::Result<BoxedUint, signature::Error> {
let bits_precision =
u32::try_from(bytes.len().saturating_mul(8)).map_err(signature::Error::from_source)?;
BoxedUint::from_be_slice(bytes, bits_precision).map_err(signature::Error::from_source)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify BoxedUint::from_be_slice signature in the rsa crate's crypto-bigint dependency
# Look for usage patterns in the crate to confirm API compatibility

# Check if there are any tests or examples using similar patterns
rg -n "BoxedUint::from_be_slice" --type rust
rg -n "to_be_bytes\|from_be_slice" --type rust -C2

Repository: EffortlessSteven/jsonwebtoken

Length of output: 196


🏁 Script executed:

# Find Cargo.toml to check rsa crate version
find . -name "Cargo.toml" -type f | head -5

Repository: EffortlessSteven/jsonwebtoken

Length of output: 85


🏁 Script executed:

# Check rsa crate dependencies
grep -A5 "rsa" Cargo.toml 2>/dev/null || echo "Cargo.toml not found in root"

Repository: EffortlessSteven/jsonwebtoken

Length of output: 448


🏁 Script executed:

# Examine the full context of the to_boxed_uint function and its usage
cat -n src/crypto/rust_crypto/rsa.rs | head -40

Repository: EffortlessSteven/jsonwebtoken

Length of output: 1820


🏁 Script executed:

# Search for all BoxedUint usage patterns in the codebase
rg -n "BoxedUint" --type rust -B2 -A2

Repository: EffortlessSteven/jsonwebtoken

Length of output: 1079


🏁 Script executed:

# Check if there are tests for the to_boxed_uint function
rg -n "to_boxed_uint" --type rust -B3 -A3

Repository: EffortlessSteven/jsonwebtoken

Length of output: 1303


🌐 Web query:

BoxedUint::from_be_slice rsa 0.10 API signature crypto-bigint

💡 Result:

In the RustCrypto RSA crate version 0.10 (currently in RC, latest 0.10.0-rc.17 as of 2026-03-10), RSA keys use crypto-bigint's BoxedUint for big integers like modulus n and exponent e. To construct an RSA public key from big-endian byte slices (e.g., for raw RSA signature verification), use RsaPublicKey::new(n, e), where n and e are BoxedUint created via BoxedUint::from_be_slice(slice). From the source code in RustCrypto/RSA src/key.rs: pub fn new(n: BoxedUint, e: BoxedUint) -> Result It validates the modulus (must be odd, non-zero) and creates BoxedMontyParams for modular arithmetic. BoxedUint::from_be_slice is a const fn method on BoxedUint (available since crypto-bigint ~0.5 per changelog), parsing big-endian bytes into a heap-allocated big integer, trimming leading zeros. Example usage for signature verification (hazmat warning: low-level, validate inputs): use rsa::{RsaPublicKey, signature::{Verifier, DigestVerifier}}; use crypto_bigint::BoxedUint; use sha2::Sha256; // Assume n_bytes and e_bytes are big-endian byte slices for n and e let n = BoxedUint::from_be_slice(&n_bytes); let e = BoxedUint::from_be_slice(&e_bytes); let pub_key = RsaPublicKey::new(n, e).expect("invalid public key"); // For PKCS1v15 signature verification: let digest = Sha256::digest(b"message"); pub_key.verify_digest(&pkcs1v15::Signature, digest, &signature_bytes)?;

Citations:


🌐 Web query:

rsa 0.10.0-rc.17 BoxedUint::from_be_slice two parameters bits_precision signature

💡 Result:

In the RustCrypto RSA crate version 0.10.0-rc.17, BoxedUint is a struct from the crypto-bigint dependency, described as a "Fixed-precision heap-allocated big unsigned integer". It is used in RSA key components like the modulus n (NonZero) and exponents. No explicit documentation or source snippets for a BoxedUint::from_be_slice method with two parameters (likely a &[u8] slice and bits_precision usize) were found in the available results. However, crypto-bigint provides methods like from_be_hex for Uint (stack-allocated counterpart), suggesting from_be_slice likely decodes a big-endian byte slice into a BoxedUint, with bits_precision specifying the fixed bit width (e.g., for RSA key sizes like 2048 bits). This method is likely used in low-level "hazmat" RSA operations, such as constructing RSA keys from components or processing raw signatures, where signatures are byte arrays decoded to bigints matching the key's bit precision. For example, in key validation, bits_precision is compared between primes and modulus (p.bits_precision.cmp(&q.bits_precision)), and resizing occurs with methods like resize_unchecked. The hazmat module provides low-level RSA functions, potentially involving signature encoding/decoding with such conversions. Official docs are at https://docs.rs/rsa/0.10.0-rc.17/rsa/ (though some builds failed; check latest). Source at https://github.com/RustCrypto/RSA. To use: enable the "hazmat" feature. Example context from key.rs source: primes.iter.fold(BoxedUint::one, |acc, p| acc.concatenating_mul(&p)).

Citations:


🏁 Script executed:

# Check if there's a Cargo.lock file that might show resolved versions
cat Cargo.lock | grep -A10 "name = \"rsa\"" | head -20

Repository: EffortlessSteven/jsonwebtoken

Length of output: 115


🌐 Web query:

site:github.com RustCrypto RSA BoxedUint from_be_slice 0.10 source code

💡 Result:

The RustCrypto RSA crate (https://github.com/RustCrypto/RSA) uses crypto_bigint::BoxedUint from the crypto-bigint crate (https://github.com/RustCrypto/crypto-bigint) for big integer arithmetic in version 0.10 (currently in RC as of March 2026, e.g., v0.10.0-rc.17). This switch was made in PR #394 (merged Feb 2025) to replace num-bigint with crypto-bigint for constant-time operations. No source code snippet for a from_be_slice method on BoxedUint was found in the search results. BoxedUint is a heap-allocated big integer type designed for cryptographic use, with constant-time operations. It likely supports decoding from big-endian byte slices via methods like from_be_bytes, from_be_slice, or decode_be, but the exact implementation is in the crypto-bigint source (likely src/integer/boxed.rs or similar). For the latest source, view: - RSA master: https://github.com/RustCrypto/RSA/blob/master/src/key.rs (uses BoxedUint) - crypto-bigint master: https://github.com/RustCrypto/crypto-bigint/tree/master/src (contains BoxedUint impl) Official docs: https://docs.rs/rsa (latest) and https://docs.rs/crypto-bigint (check for 0.10 compat). No 0.10 docs.rs page found, suggesting pre-release status.

Citations:


🏁 Script executed:

# Search for any test files or examples that show BoxedUint::from_be_slice usage
fd -e rs -type f | xargs rg -l "from_be_slice" | head -5

Repository: EffortlessSteven/jsonwebtoken

Length of output: 290


🌐 Web query:

crypto-bigint BoxedUint from_be_slice documentation API signature parameters

💡 Result:

The crypto-bigint crate provides BoxedUint as a fixed-precision heap-allocated big unsigned integer (requires the alloc feature). It includes methods like from_be_slice_vartime(&[u8]) and from_le_slice_vartime(&[u8]) for parsing from byte slices, added in version 0.6.0 per the changelog. Constant-time versions from_be_slice(&[u8]) and from_le_slice(&[u8]) were added earlier. There is no explicit documentation snippet for the exact signature of from_be_slice in the searched results, but analogous Uint::from_be_slice(bytes: &[u8]) -> Self exists as a const fn for big-endian byte slices. BoxedUint likely has pub fn from_be_slice(bytes: &[u8]) -> Result<Self, TryFromSliceError>, where TryFromSliceError is returned if the slice cannot instantiate the object (e.g., wrong length or leading zero issues). Usage requires alloc feature; it's designed for cryptographic constant-time operations.

Citations:


🏁 Script executed:

# Look for any comments or documentation about the bits_precision parameter in the RSA file
rg -n "bits_precision\|from_be_slice" src/crypto/rust_crypto/rsa.rs -B5 -A5

Repository: EffortlessSteven/jsonwebtoken

Length of output: 55


🌐 Web query:

rsa crate from_be_slice implementation 0.10 rc17 two parameters boxed_uint bits_precision

💡 Result:

In the Rust rsa crate version 0.10.0-rc.17, there is no direct from_be_slice method on BoxedUint (from the crypto-bigint dependency) that takes two parameters including bits_precision. Instead, crypto-bigint's Uint type (used internally) provides pub const fn from_be_slice(bytes: &[u8]) -> Self, which decodes big-endian bytes into a stack-allocated big integer without a precision parameter. BoxedUint is a heap-allocated wrapper around Uint. RSA key construction uses RsaPublicKey::new(n: BoxedUint, e: BoxedUint) -> Result or RsaPrivateKey::from_components(n: BoxedUint, ...), where BoxedUint values are typically created via decoding (e.g., PKCS#1/PKCS#8 parsing) or key generation. The bits parameter appears in key generation like RsaPrivateKey::new(rng, bit_size: usize), specifying modulus size, not parsing. No evidence of a two-parameter from_be_slice(bits_precision) in the crate or crypto-bigint. Key parsing likely uses from_be_slice internally during PEM/DER decoding via pkcs1/pkcs8 dependencies, trimming leading zeros and validating size against RsaPublicKey::MAX_SIZE (4096 bits).

Citations:


🏁 Script executed:

# Try to view the exact lines around from_be_slice in context
sed -n '20,35p' src/crypto/rust_crypto/rsa.rs

Repository: EffortlessSteven/jsonwebtoken

Length of output: 651


🏁 Script executed:

# Check if there are any build/test configurations that might reveal compilation status
find . -name "*.toml" -o -name "pytest.ini" -o -name "tox.ini" | head -10

Repository: EffortlessSteven/jsonwebtoken

Length of output: 100


🏁 Script executed:

# Search the entire rsa.rs file for any trait implementations or custom from_be_slice
cat src/crypto/rust_crypto/rsa.rs | grep -n "from_be_slice\|impl\|trait" | head -20

Repository: EffortlessSteven/jsonwebtoken

Length of output: 495


Fix BoxedUint::from_be_slice API call—remove the bits_precision parameter.

The BoxedUint::from_be_slice method in rsa 0.10.0-rc.17 accepts only a single parameter (&[u8]). The current call with two parameters—BoxedUint::from_be_slice(bytes, bits_precision)—is incompatible with the actual API and will not compile. Remove the bits_precision argument:

fn to_boxed_uint(bytes: &[u8]) -> std::result::Result<BoxedUint, signature::Error> {
    BoxedUint::from_be_slice(bytes).map_err(signature::Error::from_source)
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/crypto/rust_crypto/rsa.rs` around lines 24 - 28, In to_boxed_uint remove
the unused bits_precision computation and call BoxedUint::from_be_slice with
only the bytes slice (i.e., replace BoxedUint::from_be_slice(bytes,
bits_precision) with BoxedUint::from_be_slice(bytes)) and map its error with
signature::Error::from_source so the function compiles against the rsa
0.10.0-rc.17 API; keep the function signature and the final
map_err(signature::Error::from_source) behavior.

@EffortlessSteven EffortlessSteven force-pushed the codex/rust-crypto-rsa-010 branch from 587c7bc to 0ed6873 Compare April 15, 2026 10:34
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Cargo.toml`:
- Around line 43-44: The rsa dependency is referencing a release candidate (rsa
= "0.10.0-rc.17"), which is unstable; change it to the latest published stable
(e.g., rsa = "0.9.10") while preserving optional = true and features = ["sha2"],
and add a brief comment in Cargo.toml or the project upgrade notes indicating to
revisit and upgrade to rsa 0.10.0 (remove the pinned stable and switch to
0.10.x) once the final 0.10.0 release is published and API compatibility is
verified.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9e7add3d-d8b6-493b-b329-881d92a0c44d

📥 Commits

Reviewing files that changed from the base of the PR and between 587c7bc and 0ed6873.

📒 Files selected for processing (4)
  • Cargo.toml
  • src/crypto/rust_crypto/ecdsa.rs
  • src/crypto/rust_crypto/mod.rs
  • src/crypto/rust_crypto/rsa.rs

Comment thread Cargo.toml
Comment on lines +43 to +44
rand10 = { package = "rand", version = "0.10", optional = true, features = ["std", "thread_rng"], default-features = false }
rsa = { version = "0.10.0-rc.17", optional = true, features = ["sha2"] }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

rand 0.10 crate features thread_rng std

💡 Result:

In the rand 0.10 crate, the "thread_rng" feature enables the thread-local random number generator ThreadRng and the convenience function rand::rng. It is enabled by default and depends on the "std", "std_rng", and "sys_rng" features. The "std" feature (also default) enables std library functionality, including alloc support. ThreadRng uses ChaCha (12-rounds) as its CSPRNG, automatically seeded via SysRng, and provides fast, reasonably secure randomness for general use. It is available only with the "thread_rng" feature.

Citations:


🌐 Web query:

RSA crate 0.10.0 stable release

💡 Result:

The RustCrypto RSA crate (https://crates.io/crates/rsa) has not released a stable 0.10.0 version as of 2026-04-15. The latest version is 0.10.0-rc.17, released on 2026-03-10. The current stable release is 0.9.10 from 2026-01-06. The repository status indicates it is still in Phase 1 development toward 1.0, explaining the ongoing release candidates for 0.10. No evidence of a stable 0.10.0 release exists in crates.io listings, GitHub commits, or CHANGELOG.

Citations:


Consider upgrading from the RSA release candidate when 0.10.0 stable becomes available.

Using 0.10.0-rc.17 introduces stability risk since the API may change before the final stable release. As of April 2026, stable 0.10.0 has not been released (latest is 0.9.10). Pin this version and document the upgrade path when stable is available.

The thread_rng feature in rand 0.10 is valid and correctly specified—no changes needed there.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Cargo.toml` around lines 43 - 44, The rsa dependency is referencing a release
candidate (rsa = "0.10.0-rc.17"), which is unstable; change it to the latest
published stable (e.g., rsa = "0.9.10") while preserving optional = true and
features = ["sha2"], and add a brief comment in Cargo.toml or the project
upgrade notes indicating to revisit and upgrade to rsa 0.10.0 (remove the pinned
stable and switch to 0.10.x) once the final 0.10.0 release is published and API
compatibility is verified.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant